#ifndef GENERAL_TCPSERVER_H
#define GENERAL_TCPSERVER_H

#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0500
#include <WinSock2.h>
#endif

#ifdef linux
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#define EVENT__HAVE_PTHREADS
#endif

#include <stdint.h>
#include <iostream>
#include <mutex>
#include <thread>
#include <map>
#include <functional>

using  namespace std;

class TcpServerLibevent;
// tcp 连接
class ConnectionLibevent {
public:
	ConnectionLibevent(TcpServerLibevent* p,
		struct bufferevent* v,
		uint32_t fd,
		struct sockaddr_in* p1);

	ConnectionLibevent(struct bufferevent* v,
		uint32_t fd,
		struct sockaddr_in* p1);

	typedef std::function<void (char* p, uint32_t len)> OnRecvHandle;
	virtual int OnRecv(char* p, uint32_t len);  // data ready callback
	virtual int OnClose();                     // close callback 
	virtual int OnWrite();                     // write data done callback
	int WriteData(const char* p, uint16_t len);
	int SetServer(TcpServerLibevent*);
	int SetRecvHandler(OnRecvHandle);
	TcpServerLibevent* Server();
	string IpAddress();
	uint32_t SocketFd();
	int Close();
private:
	int m_bytes_send;
	int m_bytes_recv;
	TcpServerLibevent* m_parent_server;
	struct bufferevent* m_event;
	struct sockaddr_in* m_addr;
	uint32_t m_fd;
	OnRecvHandle m_recv_handle;
};

// 管理服务端
class TcpServerLibevent {
	typedef enum {
		RUNNING,
		STOP,
		FAIL
	}SERVER_STATUS;
public:
	typedef std::function<void (ConnectionLibevent*)> OnAccept;
	typedef std::function<void (ConnectionLibevent*)> OnDisconnect;

	TcpServerLibevent(int port, string bindip);
	SERVER_STATUS Status();
	~TcpServerLibevent();
	int StartServerAndRunSync(); //  同步启动服务器
	int StartServerAsync(); // 异步启动服务
	int RemoveConnection(uint32_t);
	int SetNewConnectionHandle(OnAccept);
	int SetConnectionLeaveHandle(OnDisconnect);
	int AddConnection(uint32_t fd, ConnectionLibevent* p);
	uint64_t SocketFd();
	int ConnectionCount();
	friend struct ServerCallbacks;
private:
	uint32_t  m_port;  // 监听端口号
	string  m_bind_ip;  // 绑定端口号
	int m_current_conection; //  当前连接数目
	uint16_t m_backlog;
	struct sockaddr_in m_server_addr;  // 服务器地址
	struct event_base* m_event_base;
	struct evconnlistener* m_event_listener;
	SERVER_STATUS m_status;
	thread* m_thread;
	map<uint32_t, ConnectionLibevent*> m_map_client;
	OnAccept m_handle_accept;
	OnDisconnect m_handle_disconnect;
	intptr_t mSocketFD;   // 操作系统原生socket
};

#endif